package mviewer.renderer.jogl.drawer;

import javax.media.opengl.GL2;
import mviewer.types.IDrawer;
import mviewer.types.IPolygon;
import mviewer.types.IVector;
import mviewer.types.IVertex;
import mviewer.types.Material;
import mviewer.types.SegregatedDataIterator;
import mviewer.types.Transformation;

public class ColoredPolygonDrawer implements IDrawer {

	protected GL2 gl;
	private Material lastMaterial;

	public ColoredPolygonDrawer(GL2 gl) {
		this.gl = gl;
	}

	@Override
	public void pushTransformation(Transformation transformation) {
		gl.glPushMatrix();
		applyTransformation(transformation);
	}

	@Override
	public void draw(SegregatedDataIterator<IPolygon> polygons, Material material) {
		while (polygons.hasNext())
			drawPolygon(polygons.next());
	}

	@Override
	public void popTransformation() {
		gl.glPopMatrix();
	}

	private void drawPolygon(IPolygon polygon) {
		applyMaterial(polygon.getMaterial());
		gl.glBegin(GL2.GL_POLYGON);

		for (IVertex vertex : polygon.getVertices())
			drawVertex(gl, vertex);

		gl.glEnd();
	}

	protected void drawVertex(GL2 gl, IVertex vertex) {
		IVector normal = vertex.getNormal();

		gl.glNormal3f(normal.getX(), normal.getY(), normal.getZ());
		gl.glVertex3f(vertex.getX(), vertex.getY(), vertex.getZ());
	}

	protected void applyTransformation(Transformation transformation) {
		IVector t = transformation.getTranslation(),
				r = transformation.getRotation(),
				s = transformation.getScaling();

		gl.glTranslatef(t.getX(), t.getY(), t.getZ());
		gl.glScalef(s.getX(), s.getY(), s.getZ());
		gl.glRotatef(r.getX(), 1,0,0);
		gl.glRotatef(r.getY(), 0,1,0);
		gl.glRotatef(r.getZ(), 0,0,1);
	}

	protected void applyMaterial(Material material) {
		if (lastMaterial == material)
			return;

		lastMaterial = material;
		IVector a = material.getAmbientColor(),
				d = material.getDiffuseColor(),
				s = material.getSpecularColor();
		float shininess  = material.getShininess();
		float opacity = material.getOpacity();
		float[] ambient  = new float[] {a.getX(), a.getY(), a.getZ(), opacity};
		float[] diffuse  = new float[] {d.getX(), d.getY(), d.getZ(), opacity};
		float[] specular = new float[] {s.getX(), s.getY(), s.getZ(), opacity};

		gl.glShadeModel(material.isSmooth() ? GL2.GL_SMOOTH : GL2.GL_FLAT);
		gl.glLightModelf(GL2.GL_LIGHT_MODEL_AMBIENT, GL2.GL_TRUE);
		gl.glMaterialfv(GL2.GL_FRONT, GL2.GL_AMBIENT, ambient, 0);
		gl.glMaterialfv(GL2.GL_FRONT, GL2.GL_DIFFUSE, diffuse, 0);
		gl.glMaterialfv(GL2.GL_FRONT, GL2.GL_SPECULAR, specular, 0);
		gl.glMaterialf( GL2.GL_FRONT, GL2.GL_SHININESS, shininess);
	}

	/*private void setupGoldMaterial(GL2 gl) {
		gl.glLightModelf(GL2.GL_LIGHT_MODEL_AMBIENT, GL2.GL_TRUE);
		float[] ambient  = new float[] {0.24f, 0.19f, 0.07f, 1.0f};
		float[] diffuse  = new float[] {0.75f, 0.60f, 0.22f, 1.0f};
		float[] specular = new float[] {0.62f, 0.55f, 0.36f, 1.0f};
		float shininess  = 51.2f;

		gl.glMaterialfv(GL2.GL_FRONT, GL2.GL_AMBIENT, ambient, 0);
		gl.glMaterialfv(GL2.GL_FRONT, GL2.GL_DIFFUSE, diffuse, 0);
		gl.glMaterialfv(GL2.GL_FRONT, GL2.GL_SPECULAR, specular, 0);
		gl.glMaterialf( GL2.GL_FRONT, GL2.GL_SHININESS, shininess);
	}*/
}
